/*
  Copyright (C) 2011, Kyungjoo Kim
  
  This file is part of UHM (Unassembled HyperMatrix) sparse direct solver.
  
  All rights reserved.

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.
  
  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.
  
  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  Also add information on how to contact you by electronic and paper mail.
  
  
  Kyungjoo Kim
  iamkyungjoo@gmail.com
*/
#include "uhm/common.hxx"
#include "uhm/const.hxx"
#include "uhm/util.hxx"

#include "uhm/object.hxx"

#include "uhm/operation/scheduler.hxx"
#include "uhm/operation/element.hxx"

#include "uhm/mesh/node.hxx"
#include "uhm/mesh/element.hxx"

#include "uhm/matrix/uhm/matrix.hxx"

#include "uhm/mesh/mesh.hxx"



namespace uhm {
  // --------------------------------------------------------------
  // ** LU nopiv
  void Mesh_::lu_nopiv_with_free() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();
    
#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_lu_nopiv_with_merge_and_free, true);
#else
    s->execute_elements_seq(&op_lu_nopiv_with_merge_and_free, true);
#endif
  }
  void Mesh_::lu_nopiv_without_free() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();
    
#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_lu_nopiv_with_merge_and_no_free, true);
#else
    s->execute_elements_seq(&op_lu_nopiv_with_merge_and_no_free, true);
#endif
  }

  void Mesh_::solve_lu_nopiv_1() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();
#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_solve_lu_nopiv_1_x_with_merge, 
                    true);
#else
    s->execute_elements_seq(&op_solve_lu_nopiv_1_x_with_merge, 
                            true);
#endif
  }

  void Mesh_::solve_lu_nopiv_2() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();
#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_solve_lu_nopiv_2_x_with_branch, 
                    false);
#else
    s->execute_elements_seq(&op_solve_lu_nopiv_2_x_with_branch, 
                            false);
#endif
  }

  void Mesh_::solve_lu_nopiv() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();
    this->solve_lu_nopiv_1();
    this->solve_lu_nopiv_2();
  }

  void Mesh_::check_lu_nopiv_1() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();

#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_check_lu_nopiv_1, false);
#else
    s->execute_elements_seq(&op_check_lu_nopiv_1, false);
#endif
  }

  void Mesh_::check_lu_nopiv_2() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();

#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_tree(&op_check_lu_nopiv_2, true);
#else
    s->execute_elements_seq(&op_check_lu_nopiv_2, true);
#endif
  }

  void Mesh_::check_lu_nopiv() {
    assert(this->get_scheduler()->is_loaded());
    Scheduler s = this->get_scheduler();

    this->check_lu_nopiv_1();
    this->check_lu_nopiv_2();

#ifdef UHM_MULTITHREADING_ENABLE
    s->execute_elements_seq(&op_check_solution, true);
#else
    s->execute_elements_seq(&op_check_solution, true);
#endif
  }
  
  void Mesh_::improve_lu_nopiv() {
    // ** Not working... i don't know why...it is supposed to be working

    /*
      assert(this->get_scheduler()->is_loaded());
      Scheduler s = this->get_scheduler();
      #ifdef UHM_MULTITHREADING_ENABLE

      #else
      s->execute_elements_seq(&op_solve_lu_nopiv_1_r_with_merge, 
      true);
      s->execute_elements_seq(&op_solve_lu_nopiv_2_r_with_branch, 
      false);
      s->execute_elements_seq(&op_improve_solution, true);
      #endif
    */
  }
}
